from common.views.base_views import BaseAPIView
from apps.user.models import *
from common.exceptions import (JsonAPIException,
                               ObjectNotFoundAPIException,
                               ParametersErrorAPIException)
from .error_code import ErrCode
from rest_framework.response import Response
import copy
from django.db import transaction

from apps.product.models import *

from django.db.models import Sum
from utils.showapi import FastQuery
from django.db.models import Q


# Create your views here.


class UserTeaRepoStatisticsView(BaseAPIView):
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        accessor_user = request.user
        user_id = kwargs.get('id')

        resp = {}
        if accessor_user.id == user_id:  # 获取自己
            resp.update(accessor_user.get_tea_repo_statistics())
        else:  # 获取他人茶仓数据
            other_user = User.objects.filter(id=user_id).first()
            if not other_user:
                raise JsonAPIException(code=ErrCode.USER_NOT_FOUND.name,
                                       msg=ErrCode.USER_NOT_FOUND.value,
                                       errors=[],
                                       status=404)
            if not other_user.open_repo:
                other_user.goods_block_count = GoodsBlock.objects.filter(
                    ~Q(trade_type=GoodsBlock.TradeType.TAKE_OUT.name), owner_user_id=other_user.id).count()
                other_user.save()
                resp = {
                    "nickname": other_user.nickname,
                    "avatar": other_user.avatar,
                    "open_repo": other_user.open_repo,
                    "trade_count": other_user.trade_num,
                    "goods_block_count": other_user.goods_block_count,
                }
                return Response(resp)

            resp.update(other_user.get_tea_repo_statistics())
        return Response(resp)


class UserTeaRepoAddressListView(BaseAPIView):

    def get(self, request, *args, **kwargs):
        self.only_allow_self_user_check(request, kwargs.get('id'))
        count, addresses = Address.objects.filter_by_page(offset=-1, limit=-1, user_id=self.accessor_user.id)
        self.resp['count'] = count
        self.resp['items'] = [addr.as_dict() for addr in addresses]
        return Response(self.resp)

    def post(self, request, *args, **kwargs):
        """
        """
        self.only_allow_self_user_check(request, kwargs.get('id'))
        data = copy.copy(request.data)
        data['user_id'] = self.accessor_user.id
        if not data.get('mobile', None):
            raise JsonAPIException(code=ErrCode.ADDRESS_MOBILE_EMPTY.name, msg=ErrCode, status=400)
        with transaction.atomic():
            if data['is_default']:
                Address.objects.filter(user_id=self.accessor_user.id).update(is_default=False)
            address = Address(**data)
            address.save()
            self.resp = address.as_dict()
        return Response(self.resp)


class SingleAddressView(BaseAPIView):
    def get(self, request, *_, **kwargs):
        self.only_allow_self_user_check(request, kwargs.get('id'))
        address = Address.objects.filter(id=kwargs.get('address_id')).first()
        if not address:
            raise ObjectNotFoundAPIException(code=ErrCode.ADDRESS_NOT_FOUND.name, msg=ErrCode.ADDRESS_NOT_FOUND.value)
        self.resp.update(address.as_dict())
        return Response(self.resp)

    def post(self, request, *_, **kwargs):
        self.only_allow_self_user_check(request, kwargs.get('id'))
        address = Address.objects.filter(id=kwargs.get('address_id')).first()
        data = copy.copy(request.data)
        if not address:
            raise ObjectNotFoundAPIException(code=ErrCode.ADDRESS_NOT_FOUND.name, msg=ErrCode.ADDRESS_NOT_FOUND.value)
        with transaction.atomic():
            if data['is_default']:
                Address.objects.filter(user_id=self.accessor_user.id).update(is_default=False)
        # print(data)
        address.update(**data)
        address.save()
        self.resp.update(address.as_dict())
        return Response(self.resp)


class DeleteAddressView(BaseAPIView):
    def post(self, request, *_, **kwargs):
        self.only_allow_self_user_check(request, kwargs.get('id'))
        address = Address.objects.filter(id=kwargs.get('address_id')).first()
        if not address:
            raise ObjectNotFoundAPIException(code=ErrCode.ADDRESS_NOT_FOUND.name, msg=ErrCode.ADDRESS_NOT_FOUND.value)
        address.delete()
        return Response({})


class SetTeaRepoOpenRepoView(BaseAPIView):
    def post(self, request, *_, **kwargs):
        data = copy.copy(request.data)
        if data.get('open_repo') not in [True, False]:
            raise ParametersErrorAPIException(ErrCode.SET_OPEN_REPO_PARAMETER_ERROR.name,
                                              ErrCode.SET_OPEN_REPO_PARAMETER_ERROR.value)
        user = User.objects.get(pk=request.user.id)
        user.open_repo = data['open_repo']
        user.save()
        return Response({})


def val(offset, limit):
    """
    检验参数
    :param offset:
    :param limit:
    :return:
    """
    try:
        offset = int(offset)
        limit = int(limit)
    except:
        raise JsonAPIException(ErrCode.PAGE_ARG_ERROR.name, "页码参数错误", errors=[])
    return offset, limit


class GetOrderTradingView(BaseAPIView):
    """
    交易/列表
    已卖/列表
    提仓/列表
    tea-repo/users/<str:trade>/trading
    """

    def get(self, request, *_, **kwargs):
        user = request.user

        offset = request.GET.get('offset', "")
        limit = request.GET.get('limit', "")
        trade = kwargs['trade']

        offset, limit = val(offset, limit)
        markets = []
        count = 0
        if trade == "trading":  # 交易/列表
            count, markets = MarketOrder.objects.filter_by_page(offset=offset, limit=limit, user_id=user.id,
                                                                intention_type__in=(
                                                                    MarketOrder.IntentionType.SELL.name,
                                                                    MarketOrder.IntentionType.BUY.name),
                                                                status__in=(MarketOrder.Status.ING.name,
                                                                            MarketOrder.Status.TRADE.name),
                                                                as_gift=False,
                                                                deleted_at=0)
        elif trade == "sell":  # 已卖/列表
            count, markets = MarketOrder.objects.filter_by_page(offset=offset, limit=limit, user_id=user.id,
                                                                intention_type=MarketOrder.IntentionType.SELL.name,
                                                                status=MarketOrder.Status.END.name, as_gift=False,
                                                                deleted_at=0)
        elif trade == "takeout":  # 提仓/列表
            count, markets = MarketOrder.objects.filter_by_page(offset=offset, limit=limit, user_id=user.id,
                                                                intention_type=MarketOrder.IntentionType.TAKE_OUT.name,
                                                                status=MarketOrder.Status.END.name,
                                                                as_gift=False, deleted_at=0)
        elif trade == "all":  # 全部订单
            count, markets = MarketOrder.objects.filter_by_page(offset=offset, limit=limit,
                                                                q_params=~Q(status=MarketOrder.Status.CANCELED.name),
                                                                user_id=user.id,
                                                                as_gift=False,
                                                                deleted_at=0)

        resp = {"count": count, "items": []}
        for market in markets:
            resp["items"].append({
                "market_id": market.id,
                "product_name": market.product.name,
                "price": market.offered_price,
                "count": market.count,
                "logo": market.product.logo,
                "up_down_percent": '%.2f%%' % (market.product.up_down_percent * 100),
                "intention_type": market.intention_type,
                "intention_type_map": dict(MarketOrder.IntentionType.get_choices()),
                "publish_type": market.publish_type,
                "publish_type_map": dict(MarketOrder.PublishType.get_choices()),
                "status": market.status,
                "status_map": dict(MarketOrder.Status.get_choices()),
                "as_gift": market.as_gift,
                "as_gift_append_memo": market.as_gift_append_memo if market.as_gift_append_memo else '',
                "brand_name": market.product.brand.name,
                "order_status": market.related_order_status,
                "order_status_map": dict(Order.Status.get_choices()),
                'is_comment': Product.objects.get(pk=market.product.id).commented_by(user.pk),
            })
        return Response(resp)


class DetailOrderTradingView(BaseAPIView):
    """
    交易/正在卖详情页/茶市
    GET /tea-repo/users/e6a7e4b724a245deb8354e41375415ee/trading/detail
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        market_id = kwargs["id"]
        market_order = MarketOrder.objects.filter(id=market_id).first()
        if market_order == None:
            raise JsonAPIException(ErrCode.MARKET_ORDER_NULL.name, ErrCode.MARKET_ORDER_NULL.value)
        goods = GoodsBlock.objects.filter(market_order_id=market_id)
        resp = {"direct_to_user_mobile": market_order.direct_to_user_mobile, "count": goods.count(), "items": []}
        for good in goods:
            resp["items"].append(good.get_block_detail())
        return Response(resp)


class DetailOrderSellView(BaseAPIView):
    """
    已卖/详情页/茶市
    GET /tea-repo/users/fe3bb8bc47674befbe7a39b0150372b2/sell/detail
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        market_id = kwargs["id"]

        subs = SubOrder.objects.filter(market_order_id=market_id, seller_user_id=user.id)

        sub_one = subs[0]
        sum_price = SubOrder.objects.filter(market_order_id=market_id, seller_user_id=user.id).values(
            'market_order_id').annotate(
            price_amount=Sum('amount'),
            repo_amount=Sum('repo_amount'),
            repo_real_pay_amount=Sum('repo_real_pay_amount'),
            repo_preferential_amount=Sum('repo_preferential_amount'),
            procedure_amount=Sum('procedure_amount'),
            procedure_real_pay_amount=Sum('procedure_real_pay_amount'),
            procedure_preferential_amount=Sum('procedure_preferential_amount')
        ).first()

        repo_amount = sum_price["repo_amount"]
        repo_real_pay_amount = sum_price["repo_real_pay_amount"]
        repo_preferential_amount = sum_price["repo_preferential_amount"]
        procedure_amount = sum_price["procedure_amount"]
        procedure_real_pay_amount = sum_price["procedure_real_pay_amount"]
        procedure_preferential_amount = sum_price["procedure_preferential_amount"]
        price_amount = sum_price["price_amount"]

        direct_mobile = ""
        if sub_one.create_type == SubOrder.CreateType.DIRECTIONAL_SELL_OUT.name:
            direct = True
            market = MarketOrder.objects.filter(id=market_id).first()
            direct_mobile = market.direct_to_user_mobile
        else:
            direct = False

        resp = {
            "count": subs.count(),
            "items": [],
            "buy_name": sub_one.order.buyer_user.nickname,
            "price_amount": price_amount,
            "repo_amount": repo_amount,
            "repo_real_pay_amount": repo_real_pay_amount,
            "repo_preferential_amount": repo_preferential_amount,
            "procedure_amount": procedure_amount,
            "procedure_real_pay_amount": procedure_real_pay_amount,
            "procedure_preferential_amount": procedure_preferential_amount,
            "total_amount": price_amount - repo_real_pay_amount - procedure_real_pay_amount,
            "trade_datetime": '%s %s' % (
                sub_one.repo_cost_end_datetime.strftime('%Y.%m.%d'), sub_one.repo_cost_end_datetime.strftime('%m.%d')),
            "flow": "账户余额",
            "direct": direct,
            "direct_mobile": direct_mobile
        }

        for sub in subs:
            good = GoodsBlock.objects.filter(id=sub.goods_block_id).first()
            resp["items"].append({
                'id': good.id,
                'unique_code': good.unique_code,
                'repo_id': good.repo_id,
                'repo_name': good.repo.name,
                'repo_price_per_100g_1d': good.price_per_100g_1d,
                'days': (sub.repo_cost_end_datetime - sub.repo_cost_start_datetime).days + 1,
                "procedure_amount": sub.procedure_amount,
            })

        return Response(resp)


class DetailOrderTakeOutView(BaseAPIView):
    """
    提仓/详情页/茶市
    GET /tea-repo/users/fe3bb8bc47674befbe7a39b0150372b2/takeout/detail
    """

    def get(self, request, *args, **kwargs):
        market_id = kwargs["id"]
        market_order = MarketOrder.objects.filter(id=market_id).first()
        if market_order == None:
            raise JsonAPIException(ErrCode.MARKET_ORDER_NULL.name, ErrCode.MARKET_ORDER_NULL.value)
        subs = SubOrder.objects.filter(market_order_id=market_id)
        if subs.count()==0:
            raise JsonAPIException(ErrCode.ORDER_NULL.name, ErrCode.ORDER_NULL.value)

        sub_one = subs.first()
        sum_price = SubOrder.objects.filter(market_order_id=market_id).values('market_order_id').annotate(
            repo_amount=Sum('repo_amount'),
        ).first()

        repo_amount = Decimal(0.00)
        if sum_price:
            repo_amount = Decimal(sum_price["repo_amount"])

        if sub_one.order.express_no:
            if sub_one.order.express_info_update_time == "" \
                    or sub_one.order.express_info_update_time == None \
                    or sub_one.order.express_info_update_time.hour < datetime.now().hour:
                order = Order.objects.filter(id=sub_one.order.id).first()
                express_info = FastQuery(order.express_no)
                if express_info:
                    com = express_info['com']
                    company = ExpressCompany.objects.filter(code=com).first()
                    if company == None:
                        company = ExpressCompany.objects.create(code=com, name=com)

                    order.express_company = company
                    order.express_info = express_info
                    order.express_info_update_time = datetime.now()
                order.save()
        package = []
        packs = OrderPackage.objects.filter(order=sub_one.order)
        for pack in packs:
            package.append({
                "id": pack.id,
                "name": pack.name,
                "price": pack.price,
                "avatar": pack.avatar,
                "count": pack.count
            })
        express_commany = sub_one.order.express_company
        if express_commany == None:
            express_commany = ""
        else:
            express_commany = sub_one.order.express_company.name

        resp = {
            "count": subs.count(),
            "items": [],
            "repo_amount": repo_amount.__str__(),
            "trade_datetime": '%s %s' % (
                sub_one.repo_cost_end_datetime.strftime('%Y.%m.%d'),
                sub_one.repo_cost_end_datetime.strftime('%m.%d')),
            "payment_method": sub_one.order.payment_method,
            "payment_method_map": dict(Order.PaymentMethod.get_choices()),
            "address_name": sub_one.order.address_name if sub_one.order.address_name else '',
            "address_mobile": sub_one.order.address_mobile if sub_one.order.address_mobile else '',
            "address_full_address": sub_one.order.address_full_address if sub_one.order.address_full_address else '',
            "packages_amount": sub_one.order.packages_amount,
            "package_count": packs.count(),
            "package": package,
            "express_company": express_commany,
            "express_no": sub_one.order.express_no,
            "express_info": sub_one.order.express_info,
            "express_kefu_phone": sub_one.order.express_company.kefu_phone if sub_one.order.express_company else '',
        }

        for sub in subs:
            good = GoodsBlock.objects.filter(id=sub.goods_block_id).first()
            if good:
                resp["items"].append(good.get_block_detail())
                # resp["items"].append({
                #     'id': good.id,
                #     'unique_code': good.unique_code,
                #     'repo_id': good.repo_id,
                #     'repo_name': good.repo.name,
                #     'repo_price_per_100g_1d': sub.price_per_100g_1d,
                #     'days': (sub.repo_cost_end_datetime - sub.repo_cost_start_datetime).days + 1,
                # })

        if market_order.related_order:
            resp['order_info'] = {
                "id": market_order.related_order.id,
                "repo_amount": market_order.related_order.repo_amount.__str__(),
                "as_gift_pre_pay_repo_cost_amount": market_order.related_order.as_gift_pre_pay_repo_cost_amount.__str__(),
                "repo_preferential_amount": market_order.related_order.repo_preferential_amount.__str__(),
                "amount": market_order.related_order.amount.__str__(),
                "payment_method_display": getattr(Order.PaymentMethod, market_order.related_order.payment_method, None).value if getattr(Order.PaymentMethod, market_order.related_order.payment_method, None) else '',
                "procedure_amount": market_order.related_order.procedure_amount.__str__(),
                "procedure_preferential_amount": market_order.related_order.procedure_preferential_amount.__str__(),
                "procedure_real_pay_amount": market_order.related_order.procedure_real_pay_amount.__str__(),
                "to_seller_user_amount": market_order.related_order.to_seller_user_amount.__str__(),
                "trade_datetime": market_order.related_order.get_add_time(),
                "amount_to_display": "账户余额",
                "logistics_amount": market_order.related_order.logistics_amount.__str__(),
                "logistics_preferential_amount": market_order.related_order.logistics_preferential_amount.__str__(),
                "logistics_real_pay_amount": market_order.related_order.logistics_real_pay_amount.__str__(),
                'status': market_order.related_order.status,
            }

        return Response(resp)
